#pragma once

class icmd_cmd_exec_base {
public:
	icmd_cmd_exec_base();
	virtual ~icmd_cmd_exec_base();
	virtual void execute();
	virtual icmd_cmd_exec_base* clone() = 0;
};

template <typename T>
class icmd_cmd_exec : public icmd_cmd_exec_base {
public:
	icmd_cmd_exec(T item) : _item(item);
	~icmd_cmd_exec() {}

	virtual void execute() { _item(); }
	virtual icmd_cmd_exec_base* clone() {
		return new icmd_cmd_exec(_item);
	}

private:
	T _item;
};

// Template specialization for 'null execution.'
template <>
class icmd_cmd_exec<std::nullptr_t> : public icmd_cmd_exec_base {
public:
	icmd_cmd_exec(std::nullptr_t item) {}
	~icmd_cmd_exec() {}

	virtual void execute() { } // do nothing
	virtual icmd_cmd_exec_base* clone() {
		return new icmd_cmd_exec(nullptr);
	}
};


class ICommand {
public:
	template <typename T>
	ICommand(T execobj) : _execobj(new icmd_cmd_exec<T>(bindings)) {}
	ICommand(const ICommand& ic) {
		_execobj = ic._execobj->clone();
	}

	~ICommand() { delete _execobj; }

	void execute() {
		_execobj->execute();
	}

private:
	const ICommand& operator=(const ICommand& rhs);

	icmd_cmd_exec_base* _execobj;
};
